﻿using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using Terraria.ID;
using Terraria.ModLoader.Default;
using Terraria.ModLoader.Exceptions;
using Terraria.Social;
using Terraria.Utilities;

namespace Terraria.ModLoader.IO
{
	// Token: 0x020002E4 RID: 740
	internal static class WorldIO
	{
		// Token: 0x06001C67 RID: 7271 RVA: 0x00435848 File Offset: 0x00433A48
		internal static void Save(string path, bool isCloudSave)
		{
			path = Path.ChangeExtension(path, ".twld");
			if (FileUtilities.Exists(path, isCloudSave))
			{
				FileUtilities.Copy(path, path + ".bak", isCloudSave, true);
			}
			TagCompound tagCompound = new TagCompound();
			tagCompound["chests"] = WorldIO.SaveChests();
			tagCompound["tiles"] = TileIO.SaveTiles();
			tagCompound["containers"] = TileIO.SaveContainers();
			tagCompound["npcs"] = WorldIO.SaveNPCs();
			tagCompound["tileEntities"] = TileIO.SaveTileEntities();
			tagCompound["killCounts"] = WorldIO.SaveNPCKillCounts();
			tagCompound["anglerQuest"] = WorldIO.SaveAnglerQuest();
			tagCompound["townManager"] = WorldIO.SaveTownManager();
			tagCompound["modData"] = WorldIO.SaveModData();
			TagCompound root = tagCompound;
			MemoryStream memoryStream = new MemoryStream();
			TagIO.ToStream(root, memoryStream, true);
			byte[] array = memoryStream.ToArray();
			FileUtilities.Write(path, array, array.Length, isCloudSave);
		}

		// Token: 0x06001C68 RID: 7272 RVA: 0x00435934 File Offset: 0x00433B34
		internal static void Load(string path, bool isCloudSave)
		{
			WorldIO.customDataFail = null;
			path = Path.ChangeExtension(path, ".twld");
			if (!FileUtilities.Exists(path, isCloudSave))
			{
				return;
			}
			byte[] array = FileUtilities.ReadAllBytes(path, isCloudSave);
			if (array[0] != 31 || array[1] != 139)
			{
				WorldIO.LoadLegacy(array);
				return;
			}
			TagCompound tagCompound = TagIO.FromStream(new MemoryStream(array), true);
			WorldIO.LoadChests(tagCompound.GetList<TagCompound>("chests"));
			TileIO.LoadTiles(tagCompound.GetCompound("tiles"));
			TileIO.LoadContainers(tagCompound.GetCompound("containers"));
			WorldIO.LoadNPCs(tagCompound.GetList<TagCompound>("npcs"));
			try
			{
				TileIO.LoadTileEntities(tagCompound.GetList<TagCompound>("tileEntities"));
			}
			catch (CustomModDataException ex)
			{
				WorldIO.customDataFail = ex;
				throw;
			}
			WorldIO.LoadNPCKillCounts(tagCompound.GetList<TagCompound>("killCounts"));
			WorldIO.LoadAnglerQuest(tagCompound.GetCompound("anglerQuest"));
			WorldIO.LoadTownManager(tagCompound.GetList<TagCompound>("townManager"));
			try
			{
				WorldIO.LoadModData(tagCompound.GetList<TagCompound>("modData"));
			}
			catch (CustomModDataException ex2)
			{
				WorldIO.customDataFail = ex2;
				throw;
			}
		}

		// Token: 0x06001C69 RID: 7273 RVA: 0x00435A50 File Offset: 0x00433C50
		internal static List<TagCompound> SaveChests()
		{
			List<TagCompound> list = new List<TagCompound>();
			for (int i = 0; i < 1000; i++)
			{
				Chest chest = Main.chest[i];
				if (chest != null)
				{
					List<TagCompound> list2 = PlayerIO.SaveInventory(chest.item);
					if (list2 != null)
					{
						List<TagCompound> list3 = list;
						TagCompound tagCompound = new TagCompound();
						tagCompound["items"] = list2;
						tagCompound["x"] = chest.x;
						tagCompound["y"] = chest.y;
						list3.Add(tagCompound);
					}
				}
			}
			return list;
		}

		// Token: 0x06001C6A RID: 7274 RVA: 0x00435AD4 File Offset: 0x00433CD4
		internal static void LoadChests(IList<TagCompound> list)
		{
			foreach (TagCompound tagCompound in list)
			{
				int @int = tagCompound.GetInt("x");
				int int2 = tagCompound.GetInt("y");
				int num = Chest.FindChest(@int, int2);
				if (num < 0)
				{
					num = Chest.CreateChest(@int, int2, -1);
				}
				if (num >= 0)
				{
					PlayerIO.LoadInventory(Main.chest[num].item, tagCompound.GetList<TagCompound>("items"));
				}
			}
		}

		// Token: 0x06001C6B RID: 7275 RVA: 0x00435B68 File Offset: 0x00433D68
		internal static List<TagCompound> SaveNPCs()
		{
			List<TagCompound> list = new List<TagCompound>();
			for (int i = 0; i < Main.npc.Length; i++)
			{
				NPC npc = Main.npc[i];
				if (npc.active && NPCLoader.IsModNPC(npc))
				{
					if (npc.townNPC)
					{
						TagCompound tagCompound = new TagCompound();
						tagCompound["mod"] = npc.modNPC.mod.Name;
						tagCompound["name"] = npc.modNPC.Name;
						tagCompound["displayName"] = npc.GivenName;
						tagCompound["x"] = npc.position.X;
						tagCompound["y"] = npc.position.Y;
						tagCompound["homeless"] = npc.homeless;
						tagCompound["homeTileX"] = npc.homeTileX;
						tagCompound["homeTileY"] = npc.homeTileY;
						TagCompound item = tagCompound;
						list.Add(item);
					}
					else if (NPCID.Sets.SavesAndLoads[npc.type])
					{
						TagCompound tagCompound2 = new TagCompound();
						tagCompound2["mod"] = npc.modNPC.mod.Name;
						tagCompound2["name"] = npc.modNPC.Name;
						tagCompound2["x"] = npc.position.X;
						tagCompound2["y"] = npc.position.Y;
						TagCompound item2 = tagCompound2;
						list.Add(item2);
					}
				}
			}
			return list;
		}

		// Token: 0x06001C6C RID: 7276 RVA: 0x00435D10 File Offset: 0x00433F10
		internal static void LoadNPCs(IList<TagCompound> list)
		{
			if (list == null)
			{
				return;
			}
			int num = 0;
			foreach (TagCompound tagCompound in list)
			{
				Mod mod = ModLoader.GetMod(tagCompound.GetString("mod"));
				int num2 = (mod != null) ? mod.NPCType(tagCompound.GetString("name")) : 0;
				if (num2 > 0)
				{
					while (num < 200 && Main.npc[num].active)
					{
						num++;
					}
					if (num >= 200)
					{
						break;
					}
					NPC npc = Main.npc[num];
					npc.SetDefaults(num2, -1f);
					npc.position.X = tagCompound.GetFloat("x");
					npc.position.Y = tagCompound.GetFloat("y");
					if (npc.townNPC)
					{
						npc.GivenName = tagCompound.GetString("displayName");
						npc.homeless = tagCompound.GetBool("homeless");
						npc.homeTileX = tagCompound.GetInt("homeTileX");
						npc.homeTileY = tagCompound.GetInt("homeTileY");
					}
				}
				else
				{
					((MysteryWorld)ModLoader.GetMod("ModLoader").GetModWorld("MysteryWorld")).mysteryNPCs.Add(tagCompound);
				}
			}
		}

		// Token: 0x06001C6D RID: 7277 RVA: 0x00435E80 File Offset: 0x00434080
		internal static List<TagCompound> SaveNPCKillCounts()
		{
			List<TagCompound> list = new List<TagCompound>();
			for (int i = 580; i < NPCLoader.NPCCount; i++)
			{
				if (NPC.killCount[i] > 0)
				{
					List<TagCompound> list2 = list;
					TagCompound tagCompound = new TagCompound();
					tagCompound["mod"] = NPCLoader.GetNPC(i).mod.Name;
					tagCompound["name"] = NPCLoader.GetNPC(i).Name;
					tagCompound["count"] = NPC.killCount[i];
					list2.Add(tagCompound);
				}
			}
			return list;
		}

		// Token: 0x06001C6E RID: 7278 RVA: 0x00435F08 File Offset: 0x00434108
		internal static void LoadNPCKillCounts(IList<TagCompound> list)
		{
			foreach (TagCompound tagCompound in list)
			{
				Mod mod = ModLoader.GetMod(tagCompound.GetString("mod"));
				int num = (mod != null) ? mod.NPCType(tagCompound.GetString("name")) : 0;
				if (num > 0)
				{
					NPC.killCount[num] = tagCompound.GetInt("count");
				}
				else
				{
					((MysteryWorld)ModLoader.GetMod("ModLoader").GetModWorld("MysteryWorld")).mysteryKillCounts.Add(tagCompound);
				}
			}
		}

		// Token: 0x06001C6F RID: 7279 RVA: 0x00435FB0 File Offset: 0x004341B0
		internal static TagCompound SaveAnglerQuest()
		{
			if (Main.anglerQuest < ItemLoader.vanillaQuestFishCount)
			{
				return null;
			}
			int type = Main.anglerQuestItemNetIDs[Main.anglerQuest];
			ModItem item = ItemLoader.GetItem(type);
			TagCompound tagCompound = new TagCompound();
			tagCompound["mod"] = item.mod.Name;
			tagCompound["itemName"] = item.Name;
			return tagCompound;
		}

		// Token: 0x06001C70 RID: 7280 RVA: 0x0043600C File Offset: 0x0043420C
		internal static void LoadAnglerQuest(TagCompound tag)
		{
			Mod mod = ModLoader.GetMod(tag.GetString("mod"));
			int num = (mod != null) ? mod.ItemType(tag.GetString("itemName")) : 0;
			if (num > 0)
			{
				for (int i = 0; i < Main.anglerQuestItemNetIDs.Length; i++)
				{
					if (Main.anglerQuestItemNetIDs[i] == num)
					{
						Main.anglerQuest = i;
						return;
					}
				}
			}
			Main.AnglerQuestSwap();
		}

		// Token: 0x06001C71 RID: 7281 RVA: 0x00436070 File Offset: 0x00434270
		internal static List<TagCompound> SaveTownManager()
		{
			List<TagCompound> list = new List<TagCompound>();
			foreach (Tuple<int, Point> tuple in WorldGen.TownManager._roomLocationPairs)
			{
				if (tuple.Item1 >= 580)
				{
					ModNPC npc = NPCLoader.GetNPC(tuple.Item1);
					TagCompound tagCompound = new TagCompound();
					tagCompound["mod"] = npc.mod.Name;
					tagCompound["name"] = npc.Name;
					tagCompound["x"] = tuple.Item2.X;
					tagCompound["y"] = tuple.Item2.Y;
					TagCompound item = tagCompound;
					list.Add(item);
				}
			}
			return list;
		}

		// Token: 0x06001C72 RID: 7282 RVA: 0x00436154 File Offset: 0x00434354
		internal static void LoadTownManager(IList<TagCompound> list)
		{
			if (list == null)
			{
				return;
			}
			foreach (TagCompound tagCompound in list)
			{
				Mod mod = ModLoader.GetMod(tagCompound.GetString("mod"));
				int num = (mod != null) ? mod.NPCType(tagCompound.GetString("name")) : 0;
				if (num > 0)
				{
					Point item = new Point(tagCompound.GetInt("x"), tagCompound.GetInt("y"));
					WorldGen.TownManager._roomLocationPairs.Add(Tuple.Create<int, Point>(num, item));
					WorldGen.TownManager._hasRoom[num] = true;
				}
			}
		}

		// Token: 0x06001C73 RID: 7283 RVA: 0x00436208 File Offset: 0x00434408
		internal static List<TagCompound> SaveModData()
		{
			List<TagCompound> list = new List<TagCompound>();
			foreach (ModWorld modWorld in WorldHooks.worlds)
			{
				TagCompound tagCompound = modWorld.Save();
				if (tagCompound != null)
				{
					List<TagCompound> list2 = list;
					TagCompound tagCompound2 = new TagCompound();
					tagCompound2["mod"] = modWorld.mod.Name;
					tagCompound2["name"] = modWorld.Name;
					tagCompound2["data"] = tagCompound;
					list2.Add(tagCompound2);
				}
			}
			return list;
		}

		// Token: 0x06001C74 RID: 7284 RVA: 0x0043629C File Offset: 0x0043449C
		internal static void LoadModData(IList<TagCompound> list)
		{
			foreach (TagCompound tagCompound in list)
			{
				Mod mod = ModLoader.GetMod(tagCompound.GetString("mod"));
				ModWorld modWorld = (mod != null) ? mod.GetModWorld(tagCompound.GetString("name")) : null;
				if (modWorld != null)
				{
					try
					{
						if (tagCompound.ContainsKey("legacyData"))
						{
							modWorld.LoadLegacy(new BinaryReader(new MemoryStream(tagCompound.GetByteArray("legacyData"))));
						}
						else
						{
							modWorld.Load(tagCompound.GetCompound("data"));
						}
						continue;
					}
					catch (Exception inner)
					{
						throw new CustomModDataException(mod, "Error in reading custom world data for " + mod.Name, inner);
					}
				}
				((MysteryWorld)ModLoader.GetMod("ModLoader").GetModWorld("MysteryWorld")).data.Add(tagCompound);
			}
		}

		// Token: 0x06001C75 RID: 7285 RVA: 0x00436398 File Offset: 0x00434598
		public static void SendModData(BinaryWriter writer)
		{
			ModWorld[] netWorlds = WorldHooks.NetWorlds;
			for (int i = 0; i < netWorlds.Length; i++)
			{
				ModWorld modWorld = netWorlds[i];
				writer.SafeWrite(delegate(BinaryWriter w)
				{
					modWorld.NetSend(w);
				});
			}
		}

		// Token: 0x06001C76 RID: 7286 RVA: 0x004363DC File Offset: 0x004345DC
		public static void ReceiveModData(BinaryReader reader)
		{
			ModWorld[] netWorlds = WorldHooks.NetWorlds;
			for (int i = 0; i < netWorlds.Length; i++)
			{
				ModWorld modWorld = netWorlds[i];
				try
				{
					reader.SafeRead(delegate(BinaryReader r)
					{
						modWorld.NetReceive(r);
					});
				}
				catch (IOException)
				{
				}
			}
		}

		// Token: 0x06001C77 RID: 7287 RVA: 0x00436434 File Offset: 0x00434634
		private static void LoadLegacy(byte[] buffer)
		{
			using (MemoryStream memoryStream = new MemoryStream(buffer))
			{
				using (BinaryReader binaryReader = new BinaryReader(memoryStream))
				{
					byte b = binaryReader.ReadByte();
					if (b != 0)
					{
						byte[] array = binaryReader.ReadBytes((int)b);
						if (array.Length < 1)
						{
							Array.Resize<byte>(ref array, 1);
						}
						try
						{
							WorldIO.LoadLegacyModWorld(array, binaryReader);
						}
						catch (CustomModDataException ex)
						{
							WorldIO.customDataFail = ex;
							throw;
						}
					}
				}
			}
		}

		// Token: 0x06001C78 RID: 7288 RVA: 0x004364C4 File Offset: 0x004346C4
		private static void LoadLegacyModWorld(byte[] flags, BinaryReader reader)
		{
			if (flags.Length == 0)
			{
				return;
			}
			if ((flags[0] & 1) == 1)
			{
				WorldIO.LoadLegacyChests(reader);
			}
			if ((flags[0] & 2) == 2)
			{
				TileIO.LoadLegacyTiles(reader);
			}
			if ((flags[0] & 4) == 4)
			{
				WorldIO.LoadLegacyNPCKillCounts(reader);
			}
			if ((flags[0] & 8) == 8)
			{
				TileIO.ReadContainers(reader);
			}
			if ((flags[0] & 16) == 16)
			{
				WorldIO.LoadLegacyAnglerQuest(reader);
			}
			if ((flags[0] & 32) == 32)
			{
				WorldIO.LoadLegacyModData(reader);
			}
		}

		// Token: 0x06001C79 RID: 7289 RVA: 0x00436530 File Offset: 0x00434730
		private static void LoadLegacyChests(BinaryReader reader)
		{
			short num = reader.ReadInt16();
			for (int i = 0; i < (int)num; i++)
			{
				WorldIO.LoadLegacyChest(reader);
			}
		}

		// Token: 0x06001C7A RID: 7290 RVA: 0x00436558 File Offset: 0x00434758
		private static void LoadLegacyChest(BinaryReader reader)
		{
			int x = reader.ReadInt32();
			int y = reader.ReadInt32();
			int num = Chest.FindChest(x, y);
			if (num < 0)
			{
				num = Chest.CreateChest(x, y, -1);
			}
			if (num >= 0)
			{
				ItemIO.LoadLegacyInventory(Main.chest[num].item, reader, true, false);
				return;
			}
			ItemIO.LoadLegacyInventory(new Item[40], reader, true, false);
		}

		// Token: 0x06001C7B RID: 7291 RVA: 0x004365B0 File Offset: 0x004347B0
		private static void LoadLegacyNPCKillCounts(BinaryReader reader)
		{
			ushort num = reader.ReadUInt16();
			for (ushort num2 = 0; num2 < num; num2 += 1)
			{
				string name = reader.ReadString();
				string name2 = reader.ReadString();
				int num3 = reader.ReadInt32();
				Mod mod = ModLoader.GetMod(name);
				int num4 = (mod == null) ? 0 : mod.NPCType(name2);
				if (num4 > 0)
				{
					NPC.killCount[num4] = num3;
				}
			}
		}

		// Token: 0x06001C7C RID: 7292 RVA: 0x00436610 File Offset: 0x00434810
		private static void LoadLegacyAnglerQuest(BinaryReader reader)
		{
			string name = reader.ReadString();
			string name2 = reader.ReadString();
			Mod mod = ModLoader.GetMod(name);
			int num = 0;
			if (mod != null)
			{
				num = mod.ItemType(name2);
			}
			bool flag = false;
			if (num > 0)
			{
				for (int i = 0; i < Main.anglerQuestItemNetIDs.Length; i++)
				{
					if (Main.anglerQuestItemNetIDs[i] == num)
					{
						Main.anglerQuest = i;
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				Main.AnglerQuestSwap();
			}
		}

		// Token: 0x06001C7D RID: 7293 RVA: 0x0043667C File Offset: 0x0043487C
		private static void LoadLegacyModData(BinaryReader reader)
		{
			int num = (int)reader.ReadUInt16();
			int i = 0;
			while (i < num)
			{
				string text = reader.ReadString();
				string text2 = reader.ReadString();
				byte[] array = reader.ReadBytes((int)reader.ReadUInt16());
				Mod mod = ModLoader.GetMod(text);
				ModWorld modWorld = (mod == null) ? null : mod.GetModWorld(text2);
				if (modWorld != null)
				{
					using (MemoryStream memoryStream = new MemoryStream(array))
					{
						using (BinaryReader binaryReader = new BinaryReader(memoryStream))
						{
							try
							{
								modWorld.LoadLegacy(binaryReader);
								goto IL_ED;
							}
							catch (Exception inner)
							{
								throw new CustomModDataException(mod, "Error in reading custom world data for " + mod.Name, inner);
							}
						}
					}
					goto IL_9C;
				}
				goto IL_9C;
				IL_ED:
				i++;
				continue;
				IL_9C:
				TagCompound tagCompound = new TagCompound();
				tagCompound["mod"] = text;
				tagCompound["name"] = text2;
				tagCompound["legacyData"] = array;
				TagCompound item = tagCompound;
				((MysteryWorld)ModLoader.GetMod("ModLoader").GetModWorld("MysteryWorld")).data.Add(item);
				goto IL_ED;
			}
		}

		// Token: 0x06001C7E RID: 7294 RVA: 0x0001442C File Offset: 0x0001262C
		internal static void MoveToCloud(string localPath, string cloudPath)
		{
			localPath = Path.ChangeExtension(localPath, ".twld");
			cloudPath = Path.ChangeExtension(cloudPath, ".twld");
			if (File.Exists(localPath))
			{
				FileUtilities.MoveToCloud(localPath, cloudPath);
			}
		}

		// Token: 0x06001C7F RID: 7295 RVA: 0x00014458 File Offset: 0x00012658
		internal static void MoveToLocal(string cloudPath, string localPath)
		{
			cloudPath = Path.ChangeExtension(cloudPath, ".twld");
			localPath = Path.ChangeExtension(localPath, ".twld");
			if (FileUtilities.Exists(cloudPath, true))
			{
				FileUtilities.MoveToLocal(cloudPath, localPath);
			}
		}

		// Token: 0x06001C80 RID: 7296 RVA: 0x00014485 File Offset: 0x00012685
		internal static void LoadBackup(string path, bool cloudSave)
		{
			path = Path.ChangeExtension(path, ".twld");
			if (FileUtilities.Exists(path + ".bak", cloudSave))
			{
				FileUtilities.Move(path + ".bak", path, cloudSave, true);
			}
		}

		// Token: 0x06001C81 RID: 7297 RVA: 0x004367AC File Offset: 0x004349AC
		internal static void LoadDedServBackup(string path, bool cloudSave)
		{
			path = Path.ChangeExtension(path, ".twld");
			if (FileUtilities.Exists(path, cloudSave))
			{
				FileUtilities.Copy(path, path + ".bad", cloudSave, true);
			}
			if (FileUtilities.Exists(path + ".bak", cloudSave))
			{
				FileUtilities.Copy(path + ".bak", path, cloudSave, true);
				FileUtilities.Delete(path + ".bak", cloudSave);
			}
		}

		// Token: 0x06001C82 RID: 7298 RVA: 0x0043681C File Offset: 0x00434A1C
		internal static void RevertDedServBackup(string path, bool cloudSave)
		{
			path = Path.ChangeExtension(path, ".twld");
			if (FileUtilities.Exists(path, cloudSave))
			{
				FileUtilities.Copy(path, path + ".bak", cloudSave, true);
			}
			if (FileUtilities.Exists(path + ".bad", cloudSave))
			{
				FileUtilities.Copy(path + ".bad", path, cloudSave, true);
				FileUtilities.Delete(path + ".bad", cloudSave);
			}
		}

		// Token: 0x06001C83 RID: 7299 RVA: 0x000144BA File Offset: 0x000126BA
		internal static void EraseWorld(string path, bool cloudSave)
		{
			path = Path.ChangeExtension(path, ".twld");
			if (!cloudSave)
			{
				FileOperationAPIWrapper.MoveToRecycleBin(path);
				FileOperationAPIWrapper.MoveToRecycleBin(path + ".bak");
				return;
			}
			if (SocialAPI.Cloud != null)
			{
				SocialAPI.Cloud.Delete(path);
			}
		}

		// Token: 0x040018CC RID: 6348
		public static CustomModDataException customDataFail;
	}
}
